---
output: 
  bookdown::pdf_document2:
    toc: false
    citation_package: natbib
    fig_caption: yes
    latex_engine: pdflatex
    template: ~/Dropbox/Harvard/pandoc-default-latex.tex
    keep_tex: true
always_allow_html: true
title: "Racial Attitudes and Views of Disaster"
abstract: "Abstract."
author: 
- name: "Martin Gilens"
  affiliation: "University of California, Los Angeles"
  email: gilens@ucla.edu
  orcid_id: 0000-0001-5485-6275
- name: "Tali Mendelberg"
  affiliation: "Princeton University"
  email: talim@princeton.edu
  orcid_id: 0000-0002-4494-7541
- name: "Nicholas Short"
  affiliation: "Princeton University"
  email: nick.short@princeton.edu
  orcid_id: 0000-0002-2401-8315
date: "`r format(Sys.time(), '%B %d, %Y')`"
header-includes:
    \usepackage{mathtools}
    \usepackage{natbib}
    \usepackage{pdflscape}
    \usepackage{longtable}
    \usepackage{setspace}
    \usepackage{pdfpages}
    \usepackage{caption}
    \captionsetup[table]{font=large}
    \pagenumbering{gobble}
geometry: margin=1in
fontfamily: mathpazo
fontsize: 12pt
linestretch: 2
bibliography: manuscript.bib
biblio-style: apsr2006.bst
---
\thispagestyle{empty}

\clearpage
\pagenumbering{arabic} 

\pagebreak

```{r setup, include=FALSE}

knitr::opts_chunk$set(echo = FALSE)
library(tidyverse)
library(estimatr)
library(survey)
library(kableExtra)

load("manuscript-2-datasets.RData")

# Combine the surveys, add survey_year as a variable; keep subset of variables used in analysis

combined_surveys <- survey_1_data %>% mutate(survey_year = "2021") %>%
  bind_rows(survey_2_data %>% select(-rr_index) %>% mutate(survey_year = "2023")) %>% 
  mutate(survey_year = factor(survey_year, levels = c("2021", "2023"))) %>%
  select(more_spending, more_spending_binary, more_relief, more_prevention, prefer_prevention_alt, 
         age, gender, educ, income, party, race_alt, black_multi, rr_index_alt, rr_index_alt_discrete, survey_year, weights)

# Create "White" (non-Black and non-Latinx) samples for each survey

survey_1_white <- survey_1_data %>%
  filter(!race_alt %in% c("Black", "Latinx"), # Drop those who select Latinx or only Black race
         black_multi == 0) # Drop those who selected Black in combination with some other race

survey_2_white <- survey_2_data %>%
  filter(!race_alt %in% c("Black", "Latinx"), 
         black_multi == 0) 
  
combined_surveys_white <- combined_surveys %>%
  filter(!race_alt %in% c("Black", "Latinx"), 
         black_multi == 0) 

# Create "White" (non-Black and non-Latinx) subsets for certain wording conditions in the 2023 survey

survey_2_only_nph_white <- survey_2_white %>%
  filter(condition == "natural_and_health_disasters")  %>%
  select(ResponseId, more_spending, age, gender, educ, income, party, rr_index_alt, weights) 
   
survey_2_not_nph_white <- survey_2_white %>%
  filter(condition != "natural_and_health_disasters") %>%
  mutate(condition = factor(condition, levels = c("natural_disasters", "health_disasters"))) 

# Create "White" (non-Black and non-Latinx) and Black respondent subsets of the reasons data

rr_reasons_data_white <- rr_reasons_data %>%
  semi_join(survey_1_white, by = "ResponseId")

rr_reasons_data_black <- rr_reasons_data %>%
  filter(race_alt == "Black")

# Create design objects for the 2023 survey and the combined surveys

survey_2_design <- svydesign(id = ~1, weights = ~weights, data = survey_2_data, na.rm = T)
combined_surveys_design <- svydesign(id = ~1, weights = ~weights, data = combined_surveys, na.rm = T)
```

# Figures

The code below reproduces Figure 1.

```{r attitudes-bivariate}

bivariate_1 <- lm_robust(more_spending ~ age + gender + educ + income + party + black_laziness, data = survey_2_white, se_type = "stata", weights = weights) %>% tidy() 
bivariate_2 <- lm_robust(more_spending ~ age + gender + educ + income + party + stype_index_black, data = survey_2_white, se_type = "stata", weights = weights) %>% tidy() 
bivariate_3 <- lm_robust(more_spending ~ age + gender + educ + income + party + racial_sympathy_anes, data = survey_2_white, se_type = "stata", weights = weights) %>% tidy() 
bivariate_4 <- lm_robust(more_spending ~ age + gender + educ + income + party + stype_index, data = survey_2_white, se_type = "stata", weights = weights) %>% tidy() 
bivariate_5 <- lm_robust(more_spending ~ age + gender + educ + income + party + rr_index, data = survey_2_white, se_type = "stata", weights = weights) %>% tidy() 

bivariate_1 %>%
  bind_rows(bivariate_2, bivariate_3, bivariate_4, bivariate_5) %>%
  filter(term %in% c("black_laziness", "racial_sympathy_anes", "rr_index", "stype_index", "stype_index_black")) %>%
  mutate(term = case_when(term == "black_laziness" ~ "Stereo. of Black laziness",
                          term == "racial_sympathy_anes" ~ "Racial unsympathy",
                          term == "rr_index" ~ "Racial resentment (4-item index)",
                          # term == "blame_index" ~ "Blame victims (3-item index)",
                          term == "stype_index" ~ "Ethnocentrism (6-item index)",
                          term == "stype_index_black" ~ "Anti-Black stereo. (3-item index)",),
         term = factor(term, levels = c("Ethnocentrism (6-item index)", "Anti-Black stereo. (3-item index)", "Stereo. of Black laziness", 
                                        "Racial resentment (4-item index)", "Racial unsympathy"))
         ) %>%
  ggplot(aes(x = estimate, y = term, xmin = conf.low, xmax = conf.high)) +
  geom_point() +
  geom_errorbar(width = 0.1) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  theme_minimal() +
  labs(x = NULL, y = NULL)
```

\pagebreak

The code below reproduces Figure 2.

```{r attitudes-independent}

attitudes_spending <- lm_robust(more_spending ~ age + gender + educ + income + party + black_laziness + racial_sympathy_anes + rr_index + stype_index + stype_index_black,
                                data = survey_2_white, 
                                se_type = "stata", 
                                weights = weights) %>%
  tidy() 

attitudes_spending %>%
  filter(term %in% c("black_laziness", "racial_sympathy_anes", "rr_index", "stype_index", "stype_index_black")) %>%
  mutate(term = case_when(term == "black_laziness" ~ "Stereo. of Black laziness",
                          term == "racial_sympathy_anes" ~ "Racial unsympathy",
                          term == "rr_index" ~ "Racial resentment (4-item index)",
                          # term == "blame_index" ~ "Blame victims (3-item index)",
                          term == "stype_index" ~ "Ethnocentrism (6-item index)",
                          term == "stype_index_black" ~ "Anti-Black stereo. (3-item index)",),
         term = factor(term, levels = c("Ethnocentrism (6-item index)", "Anti-Black stereo. (3-item index)", "Stereo. of Black laziness", 
                                        "Racial resentment (4-item index)", "Racial unsympathy"))
         ) %>%
  ggplot(aes(x = estimate, y = term, xmin = conf.low, xmax = conf.high)) +
  geom_point() +
  geom_errorbar(width = 0.1) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  theme_minimal() +
  labs(x = NULL, y = NULL)
```

\pagebreak

The code below reproduces Figure 3.

```{r rr-moderation-model}

rr_moderation_model_low <- lm_robust(persuasiveness ~ age + gender + income + educ + party + spending_type + rr_index_alt_discrete*reason_type,
                                     data = rr_reasons_data_white %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("Low", "Mid", "High"))),
                                     weights = weights, 
                                     se_type = "stata",
                                     clusters = ResponseId) %>%
  tidy() %>%
  filter(term == "reason_typeExplicit") %>%
  mutate(contrast = "Low")

rr_moderation_model_mid <- lm_robust(persuasiveness ~ age + gender + income + educ + party + spending_type + rr_index_alt_discrete*reason_type,
                                     data = rr_reasons_data_white %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("Mid", "High", "Low"))),
                                     weights = weights, 
                                     se_type = "stata",
                                     clusters = ResponseId) %>%
  tidy() %>%
  filter(term == "reason_typeExplicit") %>%
  mutate(contrast = "Mid")

rr_moderation_model_high <- lm_robust(persuasiveness ~ age + gender + income + educ + party + spending_type + rr_index_alt_discrete*reason_type,
                                     data = rr_reasons_data_white %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("High", "Low", "Mid"))),
                                     weights = weights, 
                                     se_type = "stata",
                                     clusters = ResponseId) %>%
  tidy() %>%
  filter(term == "reason_typeExplicit") %>%
  mutate(contrast = "High")


rr_moderation_model_low %>%
  bind_rows(rr_moderation_model_mid, rr_moderation_model_high) %>%
  mutate(contrast = factor(contrast, levels = c("High", "Mid", "Low"))) %>%
  ggplot(aes(x = estimate, y = contrast, xmin = conf.low, xmax = conf.high)) +
  geom_point() +
  geom_errorbar(width = 0.1) +
  theme_minimal() +
  geom_vline(xintercept = 0, linetype = "dashed") +
  labs(x = NULL, y = NULL)
```

\pagebreak

The code below reproduces Figure 4.

```{r bw-gap-1}

# Calculate average support for all four dependent variables by racial group

# There are 4,771 respondents
# combined_surveys %>% filter(!is.na(race_alt)) %>% select(ResponseId) %>% n_distinct()

race_means_plot <- svyby(~more_spending_binary, by = ~race_alt, design = combined_surveys_design, FUN = svymean, na.rm = TRUE) %>%
  as_tibble() %>%
  mutate(variable = "more_spending_binary",
         race_alt = case_when(race_alt == "Missing/Prefer not to say" ~ "Missing",
                         TRUE ~ race_alt),
         race_alt = factor(race_alt, levels = rev(c("Black", "White", "Asian","Latinx","Other","Missing")))
    ) %>%
  rename(estimate = more_spending_binary, std.error = se)

race_means_plot %>% 
  filter(!race_alt %in% c("Missing", "Other")) %>%
  arrange(desc(estimate)) %>%
  mutate(race_alt = factor(race_alt, levels = race_alt)) %>%
  ggplot(aes(x = estimate, y = race_alt, xmin = estimate - (1.386*std.error), xmax = estimate + (1.386*std.error))) +
  geom_bar(width = 0.5, stat = "identity") + 
  geom_errorbar(width = 0.1) + 
  theme_minimal() + 
  labs(x = NULL, y = NULL) + 
  theme(legend.position = "bottom") + 
  xlim(0,1)
```

\pagebreak

The code below reproduces Figure 5.

```{r bw-gap-2}

more_spending_race_combined <- lm_robust(more_spending ~ age + gender + educ + income + race_alt, data = combined_surveys, se_type = "stata", weights = weights) %>%
  tidy() 

more_spending_race_combined %>%
  filter(!term %in% c("genderOther", "race_altOther", "race_altMissing/Prefer not to say")) %>%
  mutate(term_group = case_when(str_sub(term, 1, 3) == "age" ~ "Age",
                                str_sub(term, 1, 6) == "gender" ~ "Gender",
                                str_sub(term, 1, 4) == "educ" ~ "Education",
                                str_sub(term, 1, 6) == "income" ~ "Income",
                                str_sub(term, 1, 8) == "race_alt" ~ "Race",
                                TRUE ~ NA_character_),
         term_group = factor(term_group, levels = c("Race", "Age", "Income", "Gender", "Education")),
         term_level = case_when(term_group == "Age" ~ str_sub(term, start = 4),
                                term_group == "Gender" ~ str_sub(term, start = 7),
                                term_group == "Education" ~ str_sub(term, start = 5),
                                term_group == "Income" ~ str_sub(term, start = 7),
                                term_group == "Race" ~ str_sub(term, start = 9),
                                TRUE ~ NA_character_),
         term_level = case_when(term_level == "Bachelor's degree or higher" ~ "BA or more",
                                TRUE ~ term_level),
         ) %>%
  group_by(term_group) %>% # Add a variable in reverse order (n to 1) for each term; used in reorder() for the y aesthetic to order y-axis
  mutate(level_order = n():1) %>%
  ungroup() %>%
  filter(!is.na(term_group)) %>% # Drop intercept
  ggplot(aes(x = estimate, y = reorder(term_level, level_order), xmin = conf.low, xmax = conf.high)) + 
  geom_point() + 
  geom_errorbar(width = 0.05) + 
  geom_vline(xintercept = 0, linetype = "dashed") +
  facet_wrap(~term_group, scales = "free_y") + 
  theme_minimal() + 
  labs(x = NULL, y = NULL)
```


\pagebreak

The code below reproduces Figure 6.

```{r attitudes-race}

attitude_means_race <- svyby(~black_laziness + racial_sympathy_anes + rr_index + stype_index + stype_index_black, by = ~race_alt, design = survey_2_design, FUN = svymean, na.rm = TRUE) %>%
  as_tibble() 

# Extract estimates and standard errors

attitude_means_race_estimates <- attitude_means_race %>%
  select(race_alt, black_laziness, racial_sympathy_anes, rr_index, stype_index, stype_index_black) %>% # blame_index
  pivot_longer(cols = -race_alt, names_to = "variable", values_to = "estimate")

attitude_means_race_errors <- attitude_means_race %>%
  select(race_alt, starts_with("se.")) %>%
  pivot_longer(cols = -race_alt, names_to = "variable", values_to = "std.error") %>%
  mutate(variable = str_remove(variable, "se."))

attitude_means_race_estimates %>%
  left_join(attitude_means_race_errors, by = c("race_alt", "variable")) %>%
  filter(race_alt %in% c("White","Black")) %>%
  mutate(variable = case_when(variable == "black_laziness" ~ "Stereo. of Black laziness",
                              #variable == "blame_index" ~ "Blame victims (3-item index)",
                              variable == "racial_sympathy_anes" ~ "Racial unsympathy",
                              variable == "rr_index" ~ "Racial resentment (4-item index)",
                              variable == "stype_index" ~ "Ethnocentrism (6-item index)",
                              variable == "stype_index_black" ~ "Black stereo. (3-item index)"),
         variable = factor(variable, levels = c("Ethnocentrism (6-item index)", "Black stereo. (3-item index)", "Stereo. of Black laziness", 
                                                "Blame victims (3-item index)", "Racial resentment (4-item index)", "Racial unsympathy"))) %>%
  ggplot(aes(x = estimate, y = variable, xmin = estimate - 1.386*std.error, xmax = estimate + 1.386*std.error, fill = race_alt)) + 
  geom_bar(stat = "identity", position = position_dodge(0.5), width = 0.5) +
  geom_errorbar(width = 0.1, position = position_dodge(0.5)) + 
  theme_minimal() + 
  labs(x = NULL, y = NULL, fill = "Respondent Race") + 
  theme(legend.position = "bottom") +
  xlim(0,1)
```

\pagebreak

## Tables

```{r kitchen-sink-tab, include = FALSE}

# The code below reproduces Table 1.

kitchen_sink_spec <- formula("more_spending ~ rr_index_alt + less_gov + trust_in_gov + need_experts + trust_in_media + exposure + age + gender + educ + income + party")

kitchen_sink_lm <- lm(kitchen_sink_spec, 
                      data = survey_1_white, 
                      weights = weights)

kitchen_sink_se <- sqrt(diag(sandwich::vcovHC(kitchen_sink_lm, type = "HC1")))

kitchen_sink_labels <- c(
                "Racial resent. (3-item index)",
                "Less gov. is better", 
                "Trust in gov.: Moderate", "Trust in gov.: Low", 
                "Believe in need for experts: Moderate", "Believe in need for experts: Low", 
                "Trust in schools and media: Moderate", "Trust in schools and media: Low",
                "Exposure: Covid", "Exposure: Disaster", "Exposure: Both", 
                "Age: 40-59", "Age: 60+",
                "Gender: Female", "Gender: Other",
                "Educ: Some college", "Educ: BA or more",
                "Income: 75-150k", "Income: 150k+",
                "Party: Independent", "Party: Republican",
                "Constant")

stargazer::stargazer(kitchen_sink_lm,
                     se = list(kitchen_sink_se),
                     dep.var.caption = "",
                     dep.var.labels = c("More on disasters"),
                     covariate.labels = kitchen_sink_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "kitchen-sink-tab",
                     out = "regression-tables/kitchen-sink-tab.tex",
                     title = "Association of racial resentment, demographics, partisan identification, and non-racial attitude measures with disaster spending support."
                     )
```

\input{regression-tables/kitchen-sink-tab.tex}

\pagebreak

```{r gen-omnibus-tab, include = FALSE}

# The code below reproduces Table 2.

# Race and demographics (2021 survey)

omnibus_1_lm <- lm(more_spending ~ race_alt + age + gender + educ + income, data = survey_1_data, weights = weights)
omnibus_1_se <- sqrt(diag(sandwich::vcovHC(omnibus_1_lm, type = "HC1")))

# Race, demographics, and RR (2021 survey)

omnibus_2_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + rr_index_alt, data = survey_1_data, weights = weights)
omnibus_2_se <- sqrt(diag(sandwich::vcovHC(omnibus_2_lm, type = "HC1")))

# Race, demographics, RR, party ID, and kitchen-sink controls (2021 survey)

omnibus_3_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + rr_index_alt + party + less_gov + trust_in_gov + need_experts + trust_in_media + exposure, data = survey_1_data, weights = weights)
omnibus_3_se <- sqrt(diag(sandwich::vcovHC(omnibus_3_lm, type = "HC1")))

# Race and demographics (2023 survey)

omnibus_4_lm <- lm(more_spending ~ race_alt + age + gender + educ + income, data = survey_2_data, weights = weights)
omnibus_4_se <- sqrt(diag(sandwich::vcovHC(omnibus_4_lm, type = "HC1")))

# Race, demographics, and RR (2023 survey)

omnibus_5_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + rr_index_alt, data = survey_2_data, weights = weights)
omnibus_5_se <- sqrt(diag(sandwich::vcovHC(omnibus_5_lm, type = "HC1")))

# Race, demographics, RR, party ID, and blame (2023 survey)

omnibus_6_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + rr_index_alt + party + blame_index, data = survey_2_data, weights = weights)
omnibus_6_se <- sqrt(diag(sandwich::vcovHC(omnibus_6_lm, type = "HC1")))

omnibus_lm <- list(omnibus_1_lm,
                   omnibus_2_lm,
                   omnibus_3_lm,
                   omnibus_4_lm,
                   omnibus_5_lm,
                   omnibus_6_lm)

omnibus_se <- list(omnibus_1_se,
                   omnibus_2_se,
                   omnibus_3_se,
                   omnibus_4_se,
                   omnibus_5_se,
                   omnibus_6_se)

omnibus_labels <- c("Race: Black", "Race: Latinx", "Race: Asian", "Race: Other", "Race: Missing", 
                    "Age: 40-59", "Age: 60+",
                    "Gender: Female", "Gender: Other",
                    "Educ: Some college", "Educ: BA or more",
                    "Income: 75-150k", "Income: 150k+",
                    "Racial resent. (3-item index)",
                    "Party: Independent", "Party: Republican",
                    "Less gov. is better",
                    "Trust in gov.: Moderate", "Trust in gov.: Low",
                    "Believe in need for experts: Moderate", "Believe in need for experts: Low",
                    "Trust in schools and media: Moderate", "Trust in schools and media: Low",
                    "Exposure: Covid", "Exposure: Disaster", "Exposure: Both",
                    "Blame victims (3-item index)",
                    # "Racial unsympathy",
                    # "Stereo. of Black laziness",
                    "Constant")

stargazer::stargazer(omnibus_lm,
                     se = omnibus_se,
                     dep.var.caption = "More on disasters",
                     dep.var.labels.include = FALSE,
                     covariate.labels = omnibus_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "omnibus-tab",
                     out = "regression-tables/omnibus-tab.tex",
                     title = "Racial attitudes explain much of the Black-White gap in disaster spending support."
                     )
```

\input{regression-tables/omnibus-tab.tex}

\pagebreak

# Supplementary Material

\setcounter{table}{0}
\setcounter{figure}{0}
\setcounter{page}{1}
\renewcommand{\thetable}{A.\arabic{table}}
\renewcommand{\thefigure}{A.\arabic{figure}}

## Figures

The code below reproduces Figure A.1 in the supplementary material.

```{r reasons-robustness-rr}

# Specify universal prevention and relief reasons

universal_reasons_prevention <- c("Q8_1", "Q8_2", "Q8_3", "Q8_4", "Q8_5", "Q8_6")
universal_reasons_relief <- c("Q11_1", "Q11_2", "Q11_3", "Q11_4", "Q11_5", "Q11_8", "Q11_9")

# Specify reasons that might be implicitly racialized

implicit_reasons <- c("Q8_7", "Q8_8", "Q11_6", "Q11_7")

# There are 36,403 observations among 1,897 respondents
# rr_reasons_data_white %>% filter(!is.na(age), !is.na(gender), !is.na(income), !is.na(educ), !is.na(party), !is.na(rr_index_alt_discrete), !is.na(reason_type)) %>% nrow()
# rr_reasons_data_white %>% filter(!is.na(age), !is.na(gender), !is.na(income), !is.na(educ), !is.na(party), !is.na(rr_index_alt_discrete), !is.na(reason_type)) %>% select(ResponseId) %>% n_distinct()

for (r in implicit_reasons){
  data_subset <- rr_reasons_data_white %>% 
    mutate(reason_type = case_when(str_sub(r, 1, 2) == "Q8" & reason %in% universal_reasons_prevention ~ "Universal", # Label universal reasons
                                   str_sub(r, 1, 2) == "Q1" & reason %in% universal_reasons_relief ~ "Universal",
                                   reason == r ~ "Implicit", # Label r as the implicit reason
                                   TRUE ~ NA_character_), # Label all others as missing (dropped below)
           reason_type = factor(reason_type, levels = c("Universal","Implicit"))) %>%
    filter(!is.na(reason_type))
  
  rr_implicit_model_low <- lm_robust(persuasiveness ~ age + gender + income + educ + party + rr_index_alt_discrete*reason_type,
                                       data = data_subset %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("Low", "Mid", "High"))),
                                       weights = weights, 
                                       se_type = "stata",
                                       clusters = ResponseId) %>%
    tidy() %>%
    filter(term == "reason_typeImplicit") %>%
    mutate(contrast = "Low")
  
  rr_implicit_model_mid <- lm_robust(persuasiveness ~ age + gender + income + educ + party + rr_index_alt_discrete*reason_type,
                                       data = data_subset %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("Mid", "High", "Low"))),
                                       weights = weights, 
                                       se_type = "stata",
                                       clusters = ResponseId) %>%
    tidy() %>%
    filter(term == "reason_typeImplicit") %>%
    mutate(contrast = "Mid")
  
  rr_implicit_model_high <- lm_robust(persuasiveness ~ age + gender + income + educ + party + rr_index_alt_discrete*reason_type,
                                       data = data_subset %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("High", "Low", "Mid"))),
                                       weights = weights, 
                                       se_type = "stata",
                                       clusters = ResponseId) %>%
    tidy() %>%
    filter(term == "reason_typeImplicit") %>%
    mutate(contrast = "High")

  lm_result <- rr_implicit_model_low %>%
    bind_rows(rr_implicit_model_mid, rr_implicit_model_high) %>%
    mutate(reason_num = r)
  
  if (r == implicit_reasons[1]){output <- lm_result} else {output <- output %>% bind_rows(lm_result)}
  
}

output %>%
  select(-term) %>%
  mutate(contrast = factor(contrast, levels = c("High", "Mid", "Low")),
         reason = case_when(reason_num == "Q8_7" ~ "A: Prevent harm to most vulnerable",
                            reason_num == "Q8_8" ~ "C: Prevent harm to front-line workers \n(black, white, Hispanic, and others)",
                            reason_num == "Q11_6" ~ "D: Relief goes to identifiable individuals",
                            reason_num == "Q11_7" ~ "B: Relief goes to truly deserving",
                            TRUE ~ NA_character_
                            ),
         reason = factor(reason, levels = c("D: Relief goes to identifiable individuals",
                                            "C: Prevent harm to front-line workers \n(black, white, Hispanic, and others)",
                                            "B: Relief goes to truly deserving",
                                            "A: Prevent harm to most vulnerable"))
         ) %>%
  ggplot(aes(x = estimate, y = reason, color = contrast, xmin = conf.low, xmax = conf.high)) +
  geom_point(position = position_dodge(width = 0.5)) +
  geom_errorbar(width = 0.1, position = position_dodge(width = 0.5)) +
  theme_minimal() +
  theme(legend.position = "bottom") + 
  geom_vline(xintercept = 0, linetype = "dashed") +
  labs(x = NULL, y = NULL, color = "RR Level")
```

\pagebreak

The code below reproduces Figure A.2 in the supplementary material.

```{r race-party-diffs}

svyby(~more_spending, by = ~race_alt+party, 
      design = subset(combined_surveys_design, race_alt %in% c("Black","White")), 
      FUN = svymean, na.rm = TRUE) %>%
  as_tibble() %>%
  mutate(across(.cols = c(more_spending, se), 
                .fns = ~case_when(race_alt == "Black" & party == "Republican" ~ 0,
                                 TRUE ~ .x)),
         lower = more_spending - 1.386*se, 
         upper = more_spending + 1.386*se,
         party = factor(party, levels = c("Republican", "Independent", "Democrat")),
         race_alt = factor(race_alt, levels = c("White", "Black"))) %>% 
  ggplot(aes(x = more_spending, y = party, xmin = lower, xmax = upper, fill = race_alt)) + 
  geom_bar(stat = "identity", width = 0.5, position = position_dodge(0.5)) + 
  geom_errorbar(width = 0.1, position = position_dodge(0.5)) + 
  theme_minimal() + 
  theme(legend.position = "bottom") + 
  labs(x = NULL, y = NULL, fill = NULL) 
  
```

\pagebreak

## Tables

```{r race-effect-tab, include = FALSE}

# The code below reproduces Table A.1 in the supplementary material.

# Just race  (combined survey)

more_spending_race_1_lm <- lm(more_spending ~ race_alt, 
                              data = combined_surveys, 
                              weights = weights)
more_spending_race_1_se <- sqrt(diag(sandwich::vcovHC(more_spending_race_1_lm, type = "HC1")))

# Race and demographics (combined survey)

more_spending_race_2_lm <- lm(more_spending ~ race_alt + age + gender + educ + income, 
                              data = combined_surveys, 
                              weights = weights)
more_spending_race_2_se <- sqrt(diag(sandwich::vcovHC(more_spending_race_2_lm, type = "HC1")))

# Join together and generate table

spending_race_lm <- list(more_spending_race_1_lm,
                         more_spending_race_2_lm)

spending_race_se <- list(more_spending_race_1_se,
                         more_spending_race_2_se)

spending_race_labels <- c("Race: Black", "Race: Latinx", "Race: Asian", "Race: Other", "Race: Missing", 
                          "Age: 40-59", "Age: 60+",
                          "Gender: Female", "Gender: Other",
                          "Educ: Some college", "Educ: BA or more",
                          "Income: 75-150k", "Income: 150k+",
                          "Constant")

stargazer::stargazer(spending_race_lm,
                     se = spending_race_se,
                     dep.var.caption = "More on disasters",
                     dep.var.labels = "",
                     covariate.labels = spending_race_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "race-effect-tab",
                     out = "regression-tables/race-effect-tab.tex",
                     title = "Ethnoracial and other demographic predictors of disaster spending support."
                     )
```

\input{regression-tables/race-effect-tab.tex}

\pagebreak

```{r race-time-effects-tab, include = FALSE}

# The code below reproduces Table A.2 in the supplementary material.

# Black-White gap in 2021 with and without controls for party ID

race_2021_lm_1 <- lm(more_spending ~ race_alt + age + gender + educ + income, 
                 data = survey_1_data, 
                 weights = weights) 
race_2021_se_1 <- sqrt(diag(sandwich::vcovHC(race_2021_lm_1, type = "HC1")))

race_2021_lm_2 <- lm(more_spending ~ race_alt + age + gender + educ + income + party, 
                 data = survey_1_data, 
                 weights = weights) 
race_2021_se_2 <- sqrt(diag(sandwich::vcovHC(race_2021_lm_2, type = "HC1")))

# Black-White gap in 2023 with and without controls for party ID

race_2023_lm_1 <- lm(more_spending ~ race_alt + age + gender + educ + income, 
                 data = survey_2_data, 
                 weights = weights) 
race_2023_se_1 <- sqrt(diag(sandwich::vcovHC(race_2023_lm_1, type = "HC1")))

race_2023_lm_2 <- lm(more_spending ~ race_alt + age + gender + educ + income + party, 
                 data = survey_2_data, 
                 weights = weights) 
race_2023_se_2 <- sqrt(diag(sandwich::vcovHC(race_2023_lm_2, type = "HC1")))

# Black-White gap in combined survey with and without controls for party ID

race_year_combined_lm_1 <- lm(more_spending ~ race_alt*survey_year + age + gender + educ + income, 
                          data = combined_surveys, 
                          weights = weights) 
race_year_combined_se_1 <- sqrt(diag(sandwich::vcovHC(race_year_combined_lm_1, type = "HC1")))

race_year_combined_lm_2 <- lm(more_spending ~ race_alt*survey_year + age + gender + educ + income + party, 
                          data = combined_surveys, 
                          weights = weights) 
race_year_combined_se_2 <- sqrt(diag(sandwich::vcovHC(race_year_combined_lm_2, type = "HC1")))

# Missing interaction term (between Missing race and 2023) arises because there is only one "Missing/prefer not to say" race observation in 2023

# race_year_combined_lm_2 %>% summary()
# 
# combined_surveys %>%
#   group_by(race_alt, survey_year) %>%
#   summarize(n = n())

race_year_lm <- list(race_2021_lm_1,
                     race_2021_lm_2,
                     race_2023_lm_1,
                     race_2023_lm_2,
                     race_year_combined_lm_1,
                     race_year_combined_lm_2)

race_year_se <- list(race_2021_se_1,
                     race_2021_se_2,
                     race_2023_se_1,
                     race_2023_se_2,
                     race_year_combined_se_1,
                     race_year_combined_se_2)

race_year_labels <- c("Race: Black", "Race: Latinx", "Race: Asian", "Race: Other", "Race: Missing", 
                    "Survey year: 2023",
                    "Age: 40-59", "Age: 60+",
                    "Gender: Female", "Gender: Other",
                    "Educ: Some college", "Educ: BA or more",
                    "Income: 75-150k", "Income: 150k+",
                    "Party: Independent", "Party: Republican",
                    "Race: Black X Survey year: 2023", "Race: Latinx X Survey year: 2023", "Race: Asian X Survey year: 2023", "Race: Other X Survey year: 2023", "Race: Missing X Survey year: 2023", 
                    "Constant")

stargazer::stargazer(race_year_lm,
                     se = race_year_se,
                     dep.var.caption = "",
                     dep.var.labels = c("More on disasters"),
                     covariate.labels = race_year_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "race-time-effects-tab",
                     out = "regression-tables/race-time-effects-tab.tex",
                     title = "Ethnoracial and other demographic predictors of disaster spending support, compared across survey years."
                     )
```

\input{regression-tables/race-time-effects-tab.tex}

\pagebreak

```{r race-wording-effects-tab, include = FALSE}

# The code below reproduces Table A.3 in the supplementary material.

race_wording_condition_lm <- lm(more_spending ~ race_alt*condition + age + gender + educ + income, 
                                data = survey_2_data, 
                                weights = weights) 
race_wording_condition_se <- sqrt(diag(sandwich::vcovHC(race_wording_condition_lm, type = "HC1")))

race_wording_labels <- c("Race: Black", "Race: Latinx", "Race: Asian", "Race: Other",
                         "Disaster type: public health (PH)", "Disaster type: natural and public health (NPH)",
                         "Age: 40-59", "Age: 60+",
                         "Gender: Female", "Gender: Other",
                         "Educ: Some college", "Educ: BA or more",
                         "Income: 75-150k", "Income: 150k+",
                         "Race: Black X PH", "Race: Latinx X PH", "Race: Asian X PH", "Race: Other X PH",
                         "Race: Black X NPH", "Race: Latinx X NPH", "Race: Asian X NPH", "Race: Other X NPH",
                         "Constant")

stargazer::stargazer(race_wording_condition_lm,
                     se = list(race_wording_condition_se),
                     dep.var.caption = c("More on disasters"),
                     dep.var.labels = "",
                     covariate.labels = race_wording_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "race-wording-effects-tab",
                     out = "regression-tables/race-wording-effects-tab.tex",
                     title = "Ethnoracial predictors of disaster spending support by type of disaster."
                     )
```

\input{regression-tables/race-wording-effects-tab.tex}

\pagebreak

```{r race-effect-spending-type-tab, include = FALSE}

# The code below reproduces Table A.4 in the supplementary material.

more_prevention_race_lm <- lm(more_prevention ~ race_alt + age + gender + educ + income, 
                              data = combined_surveys, 
                              weights = weights)
more_prevention_race_se <- sqrt(diag(sandwich::vcovHC(more_prevention_race_lm, type = "HC1")))

more_relief_race_lm <- lm(more_relief ~ race_alt + age + gender + educ + income, 
                              data = combined_surveys, 
                              weights = weights)
more_relief_race_se <- sqrt(diag(sandwich::vcovHC(more_relief_race_lm, type = "HC1")))

race_spending_type_lm <- list(more_prevention_race_lm,
                              more_relief_race_lm)

race_spending_type_se <- list(more_prevention_race_se,
                              more_relief_race_se)

race_spending_type_labels <- c("Race: Black", "Race: Latinx", "Race: Asian", "Race: Other", "Race: Missing", 
                               "Age: 40-59", "Age: 60+",
                               "Gender: Female", "Gender: Other",
                               "Educ: Some college", "Educ: BA or more",
                               "Income: 75-150k", "Income: 150k+",
                               "Constant")

stargazer::stargazer(race_spending_type_lm,
                     se = race_spending_type_se,
                     dep.var.caption = "",
                     dep.var.labels = c("More on prevention", "More on relief"),
                     covariate.labels = race_spending_type_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "race-effect-spending-type-tab",
                     out = "regression-tables/race-effect-spending-type-tab.tex",
                     title = "Ethnoracial predictors of disaster spending support by type of spending."
                     )
```

\input{regression-tables/race-effect-spending-type-tab.tex}

\pagebreak

\begin{landscape}

```{r attitudes-tab, include = FALSE}

# The code below reproduces Table A.5 in the supplementary material.

# The stereotype of Black laziness (H23a)

attitude_1a_lm <- lm(more_spending ~ black_laziness + age + gender + educ + income, data = survey_2_white, weights = weights) 
attitude_1a_se <- sqrt(diag(sandwich::vcovHC(attitude_1a_lm, type = "HC1")))

attitude_1b_lm <- lm(more_spending ~ black_laziness + age + gender + educ + income + party, data = survey_2_white, weights = weights) 
attitude_1b_se <- sqrt(diag(sandwich::vcovHC(attitude_1b_lm, type = "HC1")))

# The index of anti-Black stereotypes (H24a)

attitude_2a_lm <- lm(more_spending ~ stype_index_black + age + gender + educ + income, data = survey_2_white, weights = weights) 
attitude_2a_se <- sqrt(diag(sandwich::vcovHC(attitude_2a_lm, type = "HC1")))

attitude_2b_lm <- lm(more_spending ~ stype_index_black + age + gender + educ + income + party , data = survey_2_white, weights = weights) 
attitude_2b_se <- sqrt(diag(sandwich::vcovHC(attitude_2b_lm, type = "HC1")))

# Racial sympathy (H25a)

attitude_3a_lm <- lm(more_spending ~ racial_sympathy_anes + age + gender + educ + income, data = survey_2_white, weights = weights) 
attitude_3a_se <- sqrt(diag(sandwich::vcovHC(attitude_3a_lm, type = "HC1")))

attitude_3b_lm <- lm(more_spending ~ racial_sympathy_anes + age + gender + educ + income + party , data = survey_2_white, weights = weights) 
attitude_3b_se <- sqrt(diag(sandwich::vcovHC(attitude_3b_lm, type = "HC1")))

# Ethnocentrism (H26a)

attitude_4a_lm <- lm(more_spending ~ stype_index + age + gender + educ + income, data = survey_2_white, weights = weights) 
attitude_4a_se <- sqrt(diag(sandwich::vcovHC(attitude_4a_lm, type = "HC1")))

attitude_4b_lm <- lm(more_spending ~ stype_index + age + gender + educ + income + party , data = survey_2_white, weights = weights) 
attitude_4b_se <- sqrt(diag(sandwich::vcovHC(attitude_4b_lm, type = "HC1")))

# Racial sympathy (H27a)

attitude_5a_lm <- lm(more_spending ~ rr_index + age + gender + educ + income, data = survey_2_white, weights = weights) 
attitude_5a_se <- sqrt(diag(sandwich::vcovHC(attitude_5a_lm, type = "HC1")))

attitude_5b_lm <- lm(more_spending ~ rr_index + age + gender + educ + income + party , data = survey_2_white, weights = weights) 
attitude_5b_se <- sqrt(diag(sandwich::vcovHC(attitude_5b_lm, type = "HC1")))

# Combine them together into model and standard error lists

attitude_lm <- list(attitude_1a_lm,
                    attitude_1b_lm,
                    attitude_2a_lm,
                    attitude_2b_lm,
                    attitude_3a_lm,
                    attitude_3b_lm,
                    attitude_4a_lm,
                    attitude_4b_lm,
                    attitude_5a_lm,
                    attitude_5b_lm
                    )

attitude_se <- list(attitude_1a_se,
                    attitude_1b_se,
                    attitude_2a_se,
                    attitude_2b_se,
                    attitude_3a_se,
                    attitude_3b_se,
                    attitude_4a_se,
                    attitude_4b_se,
                    attitude_5a_se,
                    attitude_5b_se
                  )


attitude_labels <- c("Black laz. stereo. (H23a)", 
                     "Anti-Black Stereo. (H24a)", # (3-item index) 
                     "Racial unsympathy (H25a)",
                     "Ethnocentrism (H26a)", # (6-item index) 
                     "Racial resent. (H27a)", # (4-item index) 
                     "Age: 40-59", "Age: 60+",
                     "Gender: Female", "Gender: Other",
                     "Educ: Some college", "Educ: BA or more",
                     "Income: 75-150k", "Income: 150k+",
                     "Party: Independent", "Party: Republican",
                     "Constant")

stargazer::stargazer(attitude_lm,
                     se = attitude_se,
                     dep.var.caption = "",
                     dep.var.labels = c("More on disasters"),
                     covariate.labels = attitude_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "attitudes-tab",
                     out = "regression-tables/attitudes-tab.tex",
                     title = "Associations of racial attitude measures, demographics, and partisan identification with disaster spending support."
                     )
```

\input{regression-tables/attitudes-tab.tex}

\end{landscape}

\pagebreak

```{r attitudes-main-tab, include = FALSE}

# The code below reproduces Table A.6 in the supplementary material.

attitudes_spending_lm_1 <- lm(more_spending ~ racial_sympathy_anes + rr_index + black_laziness + stype_index + stype_index_black + blame_index + age + gender + educ + income + party,
                              data = survey_2_white, 
                              weights = weights)
attitudes_spending_se_1 <- sqrt(diag(sandwich::vcovHC(attitudes_spending_lm_1, type = "HC1")))

attitudes_lm <- list(attitudes_spending_lm_1)

attitudes_se <- list(attitudes_spending_se_1)

attitudes_labels <- c(
                "Racial unsympathy", 
                "Racial resent. (4-item index)",
                "Stereo. of Black laziness", 
                "Ethnocentrism (6-item index)",
                "Anti-Black stereo. (3-item index)",
                "Blame victims (3-item index)",
                "Age: 40-59", "Age: 60+",
                "Gender: Female", "Gender: Other",
                "Educ: Some college", "Educ: BA or more",
                "Income: 75-150k", "Income: 150k+",
                "Party: Independent", "Party: Republican",
                "Constant"
                )

stargazer::stargazer(attitudes_lm,
                     se = attitudes_se,
                     dep.var.caption = "",
                     dep.var.labels = c("More on disasters"),
                     covariate.labels = attitudes_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "attitudes-main-tab",
                     out = "regression-tables/attitudes-main-tab.tex",
                     title = "Association of racial attitude measures, disaster victim blame, demographics, and partisan identification with disaster spending support."
                     )
```

\input{regression-tables/attitudes-main-tab.tex}

\pagebreak

```{r omnibus-2-tab, include = FALSE}

# The code below produces Table A.7 in the online supplementary material.

# Race, demographics, and RS (2023 survey)

omnibus_7_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + racial_sympathy_anes, data = survey_2_data, weights = weights)
omnibus_7_se <- sqrt(diag(sandwich::vcovHC(omnibus_7_lm, type = "HC1")))

# Race, demographics, RS, party ID, and blame (2023 survey)

omnibus_8_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + racial_sympathy_anes + party + blame_index, data = survey_2_data, weights = weights)
omnibus_8_se <- sqrt(diag(sandwich::vcovHC(omnibus_8_lm, type = "HC1")))

# Race, demographics, and BL (2023 survey)

omnibus_9_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + black_laziness, data = survey_2_data, weights = weights)
omnibus_9_se <- sqrt(diag(sandwich::vcovHC(omnibus_9_lm, type = "HC1")))

# Race, demographics, BL, party ID, and blame (2023 survey)

omnibus_10_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + black_laziness + party + blame_index, data = survey_2_data, weights = weights)
omnibus_10_se <- sqrt(diag(sandwich::vcovHC(omnibus_10_lm, type = "HC1")))

omnibus_2_lm <- list(omnibus_7_lm,
                     omnibus_8_lm,
                     omnibus_9_lm,
                     omnibus_10_lm)

omnibus_2_se <- list(omnibus_7_se,
                     omnibus_8_se,
                     omnibus_9_se,
                     omnibus_10_se)

omnibus_2_labels <- c("Race: Black", "Race: Latinx", "Race: Asian", "Race: Other", # "Race: Missing", 
                    "Age: 40-59", "Age: 60+",
                    "Gender: Female", "Gender: Other",
                    "Educ: Some college", "Educ: BA or more",
                    "Income: 75-150k", "Income: 150k+",
                    "Racial unsympathy",
                    "Party: Independent", "Party: Republican",
                    "Blame victims (3-item index)",
                    "Stereo. of Black laziness",
                    "Constant")

stargazer::stargazer(omnibus_2_lm,
                     se = omnibus_2_se,
                     dep.var.caption = "More on disasters",
                     dep.var.labels.include = FALSE,
                     covariate.labels = omnibus_2_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "omnibus-2-tab",
                     out = "regression-tables/omnibus-2-tab.tex",
                     title = "Racial unsympathy, but not the stereotype of Black laziness, reduces the Black-White gap."
                     )

```

\input{regression-tables/omnibus-2-tab.tex}

\pagebreak

```{r predicted-diffs-tab, include = FALSE}

# The code below produces Table A.8 in the online supplementary material.

# Drop respondents with missingness on any of the variables used in the main regression

mean_analysis_data <- survey_1_data %>% 
  filter(if_all(.cols = c(age, gender, educ, income, rr_index_alt, party, less_gov, trust_in_gov, need_experts, trust_in_media, exposure), 
                .fns = ~ !is.na(.x))) 

# Run the White respondent only regression

# omnibus_3_lm <- lm(more_spending ~ race_alt + age + gender + educ + income + rr_index_alt + party + less_gov + trust_in_gov + need_experts + trust_in_media + exposure, data = survey_1_data, weights = weights)
# omnibus_3_se <- sqrt(diag(sandwich::vcovHC(omnibus_3_lm, type = "HC1")))

white_only_lm <- lm_robust(more_spending ~ age + gender + educ + income + rr_index_alt + party + less_gov + trust_in_gov + need_experts + trust_in_media + exposure, 
                           data = mean_analysis_data %>% filter(race_alt == "White"), 
                           weights = weights, 
                           se_type = "stata") %>%
  tidy() %>%
  select(term, estimate)

# Using the model matrix for White and Black only data sets, calculate average values for each variable.  Note, we use the model matrix to avoid having to convert factors to dummies by hand.

white_only_means <- model.matrix(~ age + gender + educ + income + rr_index_alt + party + less_gov + trust_in_gov + need_experts + trust_in_media + exposure, 
                                 data = mean_analysis_data %>% filter(race_alt == "White"), 
                                 weights = weights) %>%
  as_tibble() %>%
  summarize(across(.fns = ~ mean(.x, na.rm = TRUE))) 

white_only_means <- tibble(term = names(white_only_means), white_mean = as.numeric(white_only_means[1,]))  

black_only_means <- model.matrix(~ age + gender + educ + income + rr_index_alt + party + less_gov + trust_in_gov + need_experts + trust_in_media + exposure, 
                                 data = mean_analysis_data %>% filter(race_alt == "Black"), 
                                 weights = weights) %>%
  as_tibble() %>%
  summarize(across(.fns = ~ mean(.x, na.rm = TRUE))) 

black_only_means <- tibble(term = names(black_only_means), black_mean = as.numeric(black_only_means[1,]))  

# Construct the main table containing the estimated coefficients, the average values in each racial identity group, the product of the average values and the estimated coefficients, and the difference between those products.

table <- white_only_lm %>%
  left_join(white_only_means, by = "term") %>%
  left_join(black_only_means, by = "term") %>%
  rename(Term = term,
         `Coef.` = estimate,
         `White mean` = white_mean,
         `Black mean` = black_mean) %>%
  mutate(`White est.` = `Coef.` * `White mean`,
         `Counterfactual est.` = `Coef.` * `Black mean`,
         `Difference in est.` = `White est.` - `Counterfactual est.`,
         across(-Term, .fns = ~ round(100*.x, digits = 2)),
         Term = case_when(#Term == "(Intercept)" ~ "Intercept",
                          Term == "age40-59" ~ "Age: 40-59",
                          Term == "age60 or older" ~ "Age: 60+",
                          Term == "genderFemale" ~ "Gender: Female",
                          Term == "genderOther" ~ "Gender: Other",
                          Term == "educSome college" ~ "Educ: Some college",
                          Term == "educBachelor's degree or higher" ~ "Educ: BA or more",
                          Term == "income75-150k" ~ "Income: 75-150k",
                          Term == "income150k or more" ~ "Income: 150k+",
                          Term == "rr_index_alt" ~ "Racial resent. (3-item index)",
                          Term == "partyIndependent" ~ "Party: Independent",
                          Term == "partyRepublican" ~ "Party: Republican",
                          Term == "less_gov" ~ "Less. gov. is better",
                          Term == "trust_in_govModerate" ~ "Trust in gov.: Moderate",
                          Term == "trust_in_govLow" ~ "Trust in gov.: Low",
                          Term == "need_expertsModerate" ~ "Believe in need for experts: Moderate",
                          Term == "need_expertsLow" ~ "Believe in need for experts: Low",
                          Term == "trust_in_mediaModerate" ~ "Trust in schools and media: Moderate",
                          Term == "trust_in_mediaLow" ~ "Trust in schools and media: Low",
                          Term == "exposureCovid" ~ "Exposure: Covid",
                          Term == "exposureDisaster" ~ "Exposure: Disaster",
                          Term == "exposureBoth" ~ "Exposure: Both",
                          TRUE ~ NA_character_
                          )) %>%
  filter(!is.na(Term)) %>% # Drop term for intercept
  select(Term, `Coef.`, `White mean`, `White est.`, `Black mean`, `Counterfactual est.`, `Difference in est.`)
  
stargazer::stargazer(table, 
                     summary = FALSE, 
                     font.size = "scriptsize",
                     label = "predicted-diffs-tab",
                     out = "regression-tables/predicted-diffs-tab.tex",
                     title = "Attitudinal and demographic basis of B-W gap in disaster spending support")
```

\input{regression-tables/predicted-diffs-tab.tex}

\pagebreak

```{r rr-time-effects-tab, include = FALSE}

# The code below reproduces Table A.9 in the supplementary material.

# 2021 with and without controls for party ID

rr_2021_lm_1 <- lm(more_spending ~ rr_index_alt + age + gender + educ + income, 
                 data = survey_1_white, 
                 weights = weights) 
rr_2021_se_1 <- sqrt(diag(sandwich::vcovHC(rr_2021_lm_1, type = "HC1")))

rr_2021_lm_2 <- lm(more_spending ~ rr_index_alt + age + gender + educ + income + party, 
                 data = survey_1_white, 
                 weights = weights) 
rr_2021_se_2 <- sqrt(diag(sandwich::vcovHC(rr_2021_lm_2, type = "HC1")))

# 2023 with and without controls for party ID

rr_2023_lm_1 <- lm(more_spending ~ rr_index_alt + age + gender + educ + income, 
                 data = survey_2_only_nph_white, 
                 weights = weights) 
rr_2023_se_1 <- sqrt(diag(sandwich::vcovHC(rr_2023_lm_1, type = "HC1")))

rr_2023_lm_2 <- lm(more_spending ~ rr_index_alt + age + gender + educ + income + party, 
                 data = survey_2_only_nph_white, 
                 weights = weights) 
rr_2023_se_2 <- sqrt(diag(sandwich::vcovHC(rr_2023_lm_2, type = "HC1")))

# Combined survey with and without controls for party ID

rr_year_combined_lm_1 <- lm(more_spending ~ rr_index_alt + survey_year + rr_index_alt:survey_year + age + gender + educ + income, 
                          data = combined_surveys_white, 
                          weights = weights) 
rr_year_combined_se_1 <- sqrt(diag(sandwich::vcovHC(rr_year_combined_lm_1, type = "HC1")))

rr_year_combined_lm_2 <- lm(more_spending ~ rr_index_alt + survey_year + rr_index_alt:survey_year + age + gender + educ + income + party, 
                          data = combined_surveys_white, 
                          weights = weights) 
rr_year_combined_se_2 <- sqrt(diag(sandwich::vcovHC(rr_year_combined_lm_2, type = "HC1")))

rr_year_lm <- list(rr_2021_lm_1,
                   rr_2021_lm_2,
                   rr_2023_lm_1,
                   rr_2023_lm_2,
                   rr_year_combined_lm_1,
                   rr_year_combined_lm_2)

rr_year_se <- list(rr_2021_se_1,
                   rr_2021_se_2,
                   rr_2023_se_1,
                   rr_2023_se_2,
                   rr_year_combined_se_1,
                   rr_year_combined_se_2)

rr_year_labels <- c("Racial resentment (3-item index)",
                    "Survey year: 2023",
                    "Age: 40-59", "Age: 60+",
                    "Gender: Female", "Gender: Other",
                    "Educ: Some college", "Educ: BA or more",
                    "Income: 75-150k", "Income: 150k+",
                    "Party: Independent", "Party: Republican",
                    "Racial resentment (3-item index) X Survey year: 2023",
                    "Constant")

stargazer::stargazer(rr_year_lm,
                     se = rr_year_se,
                     dep.var.caption = "",
                     dep.var.labels = "More on disasters",
                     covariate.labels = rr_year_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "rr-time-effects-tab",
                     out = "regression-tables/rr-time-effects-tab.tex",
                     title = "Association of racial resentment, demographics, and partisan identification with disaster spending support, compared across survey years."
                     )
```

\input{regression-tables/rr-time-effects-tab.tex}

\pagebreak

```{r attitude-condition-tab, include = FALSE}

# The code below reproduces Table A.10 in the supplementary material.

# Stereotype of Black laziness with and without controls for party ID

blaz_condition_lm_1 <- lm(more_spending ~ condition*black_laziness + age + gender + educ + income, 
                        data = survey_2_not_nph_white, 
                        weights = weights) 
blaz_condition_se_1 <- sqrt(diag(sandwich::vcovHC(blaz_condition_lm_1, type = "HC1")))

blaz_condition_lm_2 <- lm(more_spending ~ condition*black_laziness + age + gender + educ + income + party, 
                        data = survey_2_not_nph_white, 
                        weights = weights) 
blaz_condition_se_2 <- sqrt(diag(sandwich::vcovHC(blaz_condition_lm_2, type = "HC1")))

# Racial resentment with and without controls for party ID

rres_condition_lm_1 <- lm(more_spending ~ condition*rr_index + age + gender + educ + income, 
                        data = survey_2_not_nph_white, 
                        weights = weights) 
rres_condition_se_1 <- sqrt(diag(sandwich::vcovHC(rres_condition_lm_1, type = "HC1")))

rres_condition_lm_2 <- lm(more_spending ~ condition*rr_index + age + gender + educ + income + party, 
                        data = survey_2_not_nph_white, 
                        weights = weights) 
rres_condition_se_2 <- sqrt(diag(sandwich::vcovHC(rres_condition_lm_2, type = "HC1")))

# Racial unsympathy with and without controls for party ID

rsym_condition_lm_1 <- lm(more_spending ~ condition*racial_sympathy_anes + age + gender + educ + income, 
                        data = survey_2_not_nph_white, 
                        weights = weights) 
rsym_condition_se_1 <- sqrt(diag(sandwich::vcovHC(rsym_condition_lm_1, type = "HC1")))

rsym_condition_lm_2 <- lm(more_spending ~ condition*racial_sympathy_anes + age + gender + educ + income + party, 
                        data = survey_2_not_nph_white, 
                        weights = weights) 
rsym_condition_se_2 <- sqrt(diag(sandwich::vcovHC(rsym_condition_lm_2, type = "HC1")))

# Black with and without controls for party ID

blam_condition_lm_1 <- lm(more_spending ~ condition*blame_index + age + gender + educ + income, 
                        data = survey_2_not_nph_white, 
                        weights = weights) 
blam_condition_se_1 <- sqrt(diag(sandwich::vcovHC(blam_condition_lm_1, type = "HC1")))

blam_condition_lm_2 <- lm(more_spending ~ condition*blame_index + age + gender + educ + income + party, 
                        data = survey_2_not_nph_white, 
                        weights = weights) 
blam_condition_se_2 <- sqrt(diag(sandwich::vcovHC(blam_condition_lm_2, type = "HC1")))


attitudes_condition_lm <- list(blaz_condition_lm_1,
                               blaz_condition_lm_2,
                               rres_condition_lm_1,
                               rres_condition_lm_2,
                               rsym_condition_lm_1,
                               rsym_condition_lm_2,
                               blam_condition_lm_1,
                               blam_condition_lm_2)

attitudes_condition_se <- list(blaz_condition_se_1,
                               blaz_condition_se_2,
                               rres_condition_se_1,
                               rres_condition_se_2,
                               rsym_condition_se_1,
                               rsym_condition_se_2,
                               blam_condition_se_1,
                               blam_condition_se_2)

attitudes_condition_labels <- c("Disaster type: public health (PH)",
                                "Stereo. of Black laziness", 
                                "Racial resent. (4-item index)",
                                "Racial unsympathy", 
                                "Blame victims (3-item index)",
                                "Age: 40-59", "Age: 60+",
                                "Gender: Female", "Gender: Other",
                                "Educ: Some college", "Educ: BA or more",
                                "Income: 75-150k", "Income: 150k+",
                                "Party: Independent", "Party: Republican",
                                "Stereo. of Black laziness X PH", 
                                "Racial resent. (4-item index) X PH",
                                "Racial unsympathy X PH", 
                                "Blame victims (3-item index) X PH",
                                "Constant")

stargazer::stargazer(attitudes_condition_lm,
                     se = attitudes_condition_se,
                     dep.var.caption = "",
                     dep.var.labels = c("More on disasters"),
                     covariate.labels = attitudes_condition_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "attitudes-condition-tab",
                     out = "regression-tables/attitudes-condition-tab.tex",
                     title = "Association of racial attitude measures, demographics, and partisan identification with disaster spending support, compared across type of disaster."
                     )
```

\input{regression-tables/attitudes-condition-tab.tex}

\pagebreak

```{r rr-spending-tab, include = FALSE}

# The code below reproduces Table A.11 in the supplementary material.

more_spending_rr_lm <- lm(more_spending ~ rr_index_alt + age + gender + educ + income, 
                              data = combined_surveys_white,
                              weights = weights) 
more_spending_rr_se <- sqrt(diag(sandwich::vcovHC(more_spending_rr_lm, type = "HC1")))


more_relief_rr_lm <- lm(more_relief ~ rr_index_alt + age + gender + educ + income, 
                            data = combined_surveys_white,
                            weights = weights) 
more_relief_rr_se <- sqrt(diag(sandwich::vcovHC(more_relief_rr_lm, type = "HC1")))

more_prevention_rr_lm <- lm(more_prevention ~ rr_index_alt + age + gender + educ + income, 
                            data = combined_surveys_white,
                            weights = weights) 
more_prevention_rr_se <- sqrt(diag(sandwich::vcovHC(more_prevention_rr_lm, type = "HC1")))

prefer_prevention_rr_lm <- lm(prefer_prevention_alt ~ rr_index_alt + age + gender + educ + income, 
                              data = combined_surveys_white,
                              weights = weights) 
prefer_prevention_rr_se <- sqrt(diag(sandwich::vcovHC(prefer_prevention_rr_lm, type = "HC1")))

rr_spending_lm <- list(more_spending_rr_lm,
                       more_relief_rr_lm,
                       more_prevention_rr_lm,
                       prefer_prevention_rr_lm)

rr_spending_se <- list(more_spending_rr_se,
                       more_relief_rr_se,
                       more_prevention_rr_se,
                       prefer_prevention_rr_se)

rr_spending_labels <- c("Racial Resentment (3-item index)",
                        "Age: 40-59", "Age: 60+",
                        "Gender: Female", "Gender: Other",
                        "Educ: Some college", "Educ: BA or more",
                        "Income: 75-150k", "Income: 150k+",
                        "Constant")

stargazer::stargazer(rr_spending_lm,
                     se = rr_spending_se,
                     dep.var.caption = "",
                     dep.var.labels = c("More on disasters", "More relief", "More prevention", "Prefer prevention"),
                     covariate.labels = rr_spending_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "rr-spending-tab",
                     out = "regression-tables/rr-spending-tab.tex",
                     title = "Association of racial resentment and demographics with four alternative disaster spending preferences."
                     )
```

\input{regression-tables/rr-spending-tab.tex}

\pagebreak

```{r reasons-main-tab, include = FALSE}

# The code below reproduces Table A.12 in the supplementary material.

# Note rr_reasons_data is from survey_1_white (so non-Black and non-Latinx respondents)

reasons_main_lm <- lm(persuasiveness ~ reason_type + spending_type + age + gender + educ + income + party,
                      data = rr_reasons_data_white, 
                      weights = weights)

# We have to use coeftest here to handle the clustered standard errors

# There are 1,899 unique ResponseIds in this data set
# rr_reasons_data_white %>% select(ResponseId) %>% n_distinct()

reasons_main_se <- lmtest::coeftest(reasons_main_lm, 
                                    vcov = sandwich::vcovCL,
                                    type = "HC1",
                                    df = 1898, 
                                    cluster = ~ResponseId)[,2]

reasons_labels <- c("Racialized Reason",
                    "Spending Type: Prevention",
                    "Age: 40-59", "Age: 60+",
                    "Gender: Female", "Gender: Other",
                    "Educ: Some college", "Educ: BA or more",
                    "Income: 75-150k", "Income: 150k+",
                    "Party: Independent", "Party: Republican",
                    "Constant")

stargazer::stargazer(reasons_main_lm,
                     se = list(reasons_main_se),
                     dep.var.caption = "",
                     dep.var.labels = c("Persuasiveness"),
                     covariate.labels = reasons_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "reasons-main-tab",
                     out = "regression-tables/reasons-main-tab.tex",
                     title = "Difference in the predictive power of a racialized reason for disaster support relative to non-racialized reasons."
                     )
```

\input{regression-tables/reasons-main-tab.tex}

\pagebreak

```{r reasons-moderation-tab, include = FALSE}

# The code below reproduces Table A.13 in the supplementary material.

reasons_moderation_lm_1 <- lm(persuasiveness ~ reason_type*rr_index_alt_discrete + spending_type + age + gender + educ + income + party,
                            data = rr_reasons_data_white %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("Low", "Mid", "High"))),
                            weights = weights) 

reasons_moderation_se_1 <- lmtest::coeftest(reasons_moderation_lm_1, 
                                          vcov = sandwich::vcovCL,
                                          type = "HC1",
                                          df = 1898, # 
                                          cluster = ~ResponseId)[,2]

reasons_moderation_lm_2 <- lm(persuasiveness ~ reason_type*rr_index_alt_discrete + spending_type + age + gender + educ + income + party,
                            data = rr_reasons_data_white %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("Mid", "High", "Low"))),
                            weights = weights) 

reasons_moderation_se_2 <- lmtest::coeftest(reasons_moderation_lm_2, 
                                          vcov = sandwich::vcovCL,
                                          type = "HC1",
                                          df = 1898, # 
                                          cluster = ~ResponseId)[,2]

reasons_moderation_lm_3 <- lm(persuasiveness ~ reason_type*rr_index_alt_discrete + spending_type + age + gender + educ + income + party,
                            data = rr_reasons_data_white %>% mutate(rr_index_alt_discrete = factor(rr_index_alt_discrete, levels = c("High", "Low", "Mid"))),
                            weights = weights) 

reasons_moderation_se_3 <- lmtest::coeftest(reasons_moderation_lm_3, 
                                          vcov = sandwich::vcovCL,
                                          type = "HC1",
                                          df = 1898, # 
                                          cluster = ~ResponseId)[,2]

reasons_moderation_lm <- list(reasons_moderation_lm_1,
                              reasons_moderation_lm_2,
                              reasons_moderation_lm_3)

reasons_moderation_se <- list(reasons_moderation_se_1,
                              reasons_moderation_se_2,
                              reasons_moderation_se_3)

reasons_mod_labels <- c("Racialized Reason",
                        "Racial Resent. (3-item index): Mid", "Racial Resent. (3-item index): High", "Racial Resent. (3-item index): Low",
                        "Spending Type: Prevention",
                        "Age: 40-59", "Age: 60+",
                        "Gender: Female", "Gender: Other",
                        "Educ: Some college", "Educ: BA or more",
                        "Income: 75-150k", "Income: 150k+",
                        "Party: Independent", "Party: Republican",
                        "Racial Resent. (3-item index): Mid X Racialized Reason", "Racial Resent. (3-item index): High X Racialized Reason", "Racial Resent. (3-item index): Low X Racialized Reason",
                        "Constant")

stargazer::stargazer(reasons_moderation_lm,
                     se = reasons_moderation_se,
                     dep.var.caption = "",
                     dep.var.labels = c("Persuasiveness"),
                     covariate.labels = reasons_mod_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "reasons-moderation-tab",
                     out = "regression-tables/reasons-moderation-tab.tex",
                     title = "Difference in the predictive power of a racialized reason for disaster support relative to non-racialized reasons, by respondents’ level of racial resentment."
                     )

```

\input{regression-tables/reasons-moderation-tab.tex}

\pagebreak

```{r reasons-black-tab, include = FALSE}

# The code below reproduces Table A.14 in the supplementary material.

reasons_black_lm <- lm(persuasiveness ~ reason_type + spending_type + age + gender + educ + income + party,
                       data = rr_reasons_data_black,
                       weights = weights)


# We have to use coeftest here to handle the clustered standard errors

# There are 290 unique ResponseIds in this data set
# rr_reasons_data_black %>% select(ResponseId) %>% n_distinct()

reasons_black_se <- lmtest::coeftest(reasons_black_lm,
                                    vcov = sandwich::vcovCL,
                                    type = "HC1",
                                    df = 289, #
                                    cluster = ~ResponseId)[,2]

reasons_labels <- c("Racialized Reason",
                    "Spending Type: Prevention",
                    "Age: 40-59", "Age: 60+",
                    "Gender: Female", "Gender: Other",
                    "Educ: Some college", "Educ: BA or more",
                    "Income: 75-150k", "Income: 150k+",
                    "Party: Independent", "Party: Democratic",
                    "Constant")

stargazer::stargazer(reasons_black_lm,
                     se = list(reasons_black_se),
                     dep.var.caption = "",
                     dep.var.labels = c("Persuasiveness"),
                     covariate.labels = reasons_labels,
                     star.cutoffs = c(0.05, 0.01, 0.001),
                     no.space = TRUE,
                     df = FALSE,
                     header = FALSE,
                     omit.stat = c("f"),
                     font.size = "scriptsize",
                     label = "reasons-black-tab",
                     out = "regression-tables/reasons-black-tab.tex",
                     title = "Difference in the predictive power of a racialized reason for disaster support relative to non-racialized reasons, for Black respondents."
                     )
```

\input{regression-tables/reasons-black-tab.tex}

\pagebreak

Tables A.15, A.16, and A.17 in the supplementary material are descriptive and were manually assembled.
